home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Chess++ 3.0.1 / source / CChessPane.cp < prev    next >
Text File  |  1993-05-26  |  7KB  |  264 lines

  1. ////////////
  2. //
  3. //    CChessPane.cp
  4. //
  5. //    Pane methods for a chess board.
  6. //
  7. //    Copyright © 1993 Steven J. Bushell. All rights reserved.
  8. //
  9. ////////////
  10.  
  11. #include <CBartender.h>
  12. #include <CWindow.h>
  13. #include <string.h>
  14. #include <oops.h>
  15. #include <global.h>
  16. #include "CChessDoc.h"
  17. #include "CChessPane.h"
  18. #include "CChessBoard.h"
  19. #include "CPawn.h"
  20. #include "CKnight.h"
  21. #include "CBishop.h"
  22. #include "CRook.h"
  23. #include "CQueen.h"
  24. #include "CKing.h"
  25. #include "CBrain.h"
  26. #include "ChessCommands.h"
  27.  
  28. extern    CBureaucrat *gGopher;
  29. extern    CChessBoard    *gChessBoard;
  30. extern    CBrain        *gBrain;
  31. extern    CBartender    *gBartender;
  32. extern    RgnHandle    gUtilRgn;
  33. extern    RgnHandle    gChessBoardRgnHandle;
  34. extern    Cursor        gChessCursor,gScopeCursor;
  35. extern    CursHandle    gWatchCursor;
  36.  
  37. void CChessPane::IChessPane(CView *anEnclosure, CBureaucrat *aSupervisor,
  38.                             short aWidth, short aHeight,
  39.                             short aHEncl, short aVEncl,
  40.                             SizingOption aHSizing, SizingOption aVSizing)
  41. {
  42.     register rank,file;
  43.     
  44.     CPane::IPane(anEnclosure, aSupervisor, aWidth, aHeight,
  45.                             aHEncl, aVEncl, aHSizing, aVSizing);
  46.  
  47.     itsChessBoard = new CChessBoard;
  48.     itsChessBoard->IChessBoard(this);
  49.     gChessBoard = itsChessBoard;
  50.         
  51.     SetWantsClicks(true);
  52. }
  53.  
  54.  
  55. /***
  56.  * Draw
  57.  *
  58.  *    In this method, you draw whatever you need to display in
  59.  *    your pane. The area parameter gives the portion of the 
  60.  *    pane that needs to be redrawn. Area is in frame coordinates.
  61.  *
  62.  ***/
  63.  
  64. void CChessPane::Draw(Rect *area)
  65. {
  66.     register    rank,file;
  67.     RGBColor    color;
  68.     Rect        aRect;
  69.     CChessPiece    *thePiece;
  70.     
  71.     // Draw Chess board pattern
  72.     color.blue = color.green = 0;
  73.     color.red = -1;
  74.     RGBForeColor(&color);
  75.     PenMode(srcCopy);
  76.     PaintRgn(gChessBoardRgnHandle);
  77.     
  78.     // have fun with board & pieces
  79.     ForeColor(blackColor);
  80.     for (rank=1;rank<=8;rank++)
  81.         for(file=1;file<=8;file++) {
  82.             thePiece = itsChessBoard->theBoard[rank][file];
  83.             if (thePiece) {
  84.                 thePiece->Draw(rank,file);
  85.             }
  86.         }
  87.     if (!itsChessBoard->awaitingFirstClick)
  88.         DrawSelectedSquare();
  89. }
  90.  
  91. void CChessPane::DrawSelectedSquare(void)
  92. {
  93.     register    rankQD = (itsChessBoard->firstClickRank-1) << 5,
  94.                 fileQD = (itsChessBoard->firstClickFile-1) << 5;
  95.     Rect    aRect;
  96.  
  97.     // invert square to highlight selection
  98.     SetRect(&aRect, rankQD, fileQD, rankQD+32, fileQD+32);
  99.     InvertRect(&aRect);
  100. }
  101.  
  102.  
  103. void CChessPane::ShowSelectedSquare(void)
  104. {
  105.     register    rankQD = (itsChessBoard->firstClickRank-1) << 5,
  106.                 fileQD = (itsChessBoard->firstClickFile-1) << 5;
  107.     Rect    aRect;
  108.  
  109.     // invalidate square to force redraw
  110.     SetRect(&aRect, rankQD, fileQD, rankQD+32, fileQD+32);
  111.     InvalRect(&aRect);
  112. }
  113.  
  114.     
  115. void CChessPane::ShowMove(short rank, short file)
  116. {
  117. #define DELAY 6
  118.     register    i,
  119.                 rankQD = (itsChessBoard->firstClickRank-1) << 5,
  120.                 fileQD = (itsChessBoard->firstClickFile-1) << 5;
  121.     Rect        aRect;
  122.     long        dummy;
  123.  
  124.     // invalidate first square to force redraw
  125.     SetRect(&aRect, rankQD, fileQD, rankQD+32, fileQD+32);
  126.     for (i=0;i<6;i++)
  127.     {
  128.         InvertRect(&aRect);
  129.         Delay(DELAY,&dummy);
  130.     }
  131.     InvalRect(&aRect);
  132.  
  133.     // invalidate second square to force redraw
  134.     rankQD = (rank-1) << 5;
  135.     fileQD = (file-1) << 5;
  136.     SetRect(&aRect, rankQD, fileQD, rankQD+32, fileQD+32);
  137.     for (i=0;i<6;i++)
  138.     {
  139.         InvertRect(&aRect);
  140.         Delay(DELAY,&dummy);
  141.     }
  142.     InvalRect(&aRect);    
  143. }
  144.  
  145.  
  146. /***
  147.  * DoClick
  148.  *
  149.  *    The mouse went down in the pane.
  150.  *    In this method you do whatever is appropriate for your
  151.  *    application. HitPt is given in frame coordinates. The other
  152.  *    parameters, modiferKeys and when, are taken from the event
  153.  *    record.
  154.  *
  155.  *    If you want to implement mouse tracking, this is the method
  156.  *    to do it in. You need to create a subclass of CMouseTask and
  157.  *    pass it in a TrackMouse() message to the pane.
  158.  *
  159.  ***/ 
  160.  
  161. void CChessPane::DoClick(Point hitPt, short modifierKeys, long when)
  162.  
  163. {
  164.     if (gBrain->isBrainsMove)     // we shouldn't do anything while
  165.          return;            // the computer is thinking
  166.     else
  167.         itsChessBoard->DoClick(hitPt, modifierKeys, when);
  168. }
  169.  
  170.  
  171. void CChessPane::RegisterMove(short rank, short file)
  172. {
  173.     short        firstClickRank = itsChessBoard->firstClickRank,
  174.                 firstClickFile = itsChessBoard->firstClickFile;
  175.     CChessPiece *aPiece = itsChessBoard->theBoard[rank][file],
  176.                 *myPiece = itsChessBoard->theBoard[firstClickRank][firstClickFile];
  177.                 
  178.     if (aPiece)
  179.         aPiece->Dispose();
  180.     itsChessBoard->theBoard[rank][file] = myPiece;
  181.     itsChessBoard->theBoard[firstClickRank][firstClickFile] = (CChessPiece *)0L;
  182.     
  183.     itsChessBoard->lastFirstClickRank = firstClickRank;
  184.     itsChessBoard->lastFirstClickFile = firstClickFile;
  185.     itsChessBoard->lastSecondClickRank = rank;
  186.     itsChessBoard->lastSecondClickFile = file;
  187.     
  188.     myPiece->RegisterMove(rank,file);
  189. }
  190.  
  191. /***
  192.  * HitSamePart
  193.  *
  194.  *    Test whether pointA and pointB are in the same part.
  195.  *    "The same part" means different things for different applications.
  196.  *    In the default method, "the same part" means "in the same pane."
  197.  *    If you want a different behavior, override this method. For instance,
  198.  *    two points might be in the same part if they're within n pixels
  199.  *  of each other.
  200.  *
  201.  *    PointA and pointB are both in frame coordinates.
  202.  *
  203.  ***/
  204.  
  205. Boolean     CChessPane::HitSamePart(Point pointA, Point pointB)
  206.  
  207. {
  208.     return inherited::HitSamePart(pointA, pointB);
  209. }
  210.  
  211.  
  212. /***
  213.  * AdjustCursor
  214.  *
  215.  *    If you want the cursor to have a different shape in your pane,
  216.  *    do it in this method. If you want a different cursor for different
  217.  *    parts of the same pane, you'll need to change the mouseRgn like this:
  218.  *        1. Create a region for the "special area" of your pane.
  219.  *        2. Convert this region to global coordinates
  220.  *        3. Set the mouseRgn to the intersection of this region
  221.  *           and the original mouseRgn: SectRgn(mouseRgn, myRgn, mouseRgn);
  222.  *
  223.  *    The default method just sets the cursor to the arrow. If this is fine
  224.  *    for you, don't override this method.
  225.  *
  226.  ***/
  227.  
  228. void CChessPane::AdjustCursor(Point where, RgnHandle mouseRgn)
  229.  
  230. {
  231.     register    rank,file;
  232.     short        pieceColor = NoColor,myColor = itsChessBoard->myColor;
  233.     
  234.     // if the Brain is thinking, set the cursor to a watch and get out
  235.     if (gBrain->isBrainsMove)
  236.     {
  237.         SetCursor(*gWatchCursor);
  238.         return;
  239.     }
  240.     
  241.     rank = (where.h >> 5) + 1;
  242.     file = (where.v >> 5) + 1;
  243.     
  244.     if (itsChessBoard->theBoard[rank][file])
  245.         pieceColor = itsChessBoard->theBoard[rank][file]->itsColor;
  246.  
  247.     if (itsChessBoard->awaitingFirstClick)
  248.     {
  249.         if (pieceColor == myColor)
  250.             SetCursor(&gChessCursor);
  251.         else
  252.             inherited::AdjustCursor(where, mouseRgn);
  253.     }
  254.     else
  255.     {
  256.         if ((pieceColor != myColor) &&
  257.             (itsChessBoard->
  258.                 theBoard[itsChessBoard->firstClickRank][itsChessBoard->firstClickFile]->
  259.                     IsValidMove(itsChessBoard,rank,file)))
  260.                 SetCursor(&gScopeCursor);
  261.         else
  262.             inherited::AdjustCursor(where, mouseRgn);
  263.     }
  264. }